package org.ling.xuan.action.check;

import b.d.S;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiCodeBlock;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiMethodCallExpression;
import com.intellij.psi.PsiModifierList;
import com.intellij.psi.PsiReturnStatement;
import com.intellij.psi.PsiType;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.ling.xuan.util.FileLogUtil;
import org.ling.xuan.util.LoggerUtil;
import org.ling.xuan.util.LxIoUtil;
import org.ling.xuan.util.LxOptional;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

public class LxPsiInterfaceAction extends AnAction {
    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {
        Project project = e.getProject();
        String filePath = LxOptional.of(e, c -> c.getDataContext().getData(CommonDataKeys.VIRTUAL_FILE).getPath()).orElse("");
        String inputStr = Messages.showInputDialog("请输入文件,多个;分隔", "路径", Messages.getInformationIcon());
        File targetFile = new File(LxIoUtil.getWorkHome()+"/interface-check/"+ Objects.requireNonNull(e.getProject()).getName()+".txt");
        Set<String> set = new HashSet<>();
        if (StrUtil.isNotBlank(inputStr)) {
            String[] arr = inputStr.split(";");
            for (int i = 0; i < arr.length; i++) {
                set.addAll(FileUtil.readUtf8Lines(arr[i]));
            }
        }
        if(set.size()==0){
            return;
        }
        if (FileUtil.isFile(filePath) && filePath.endsWith(".java")) {
            checkFile(project,new File(filePath),set,targetFile);
        } else if (FileUtil.isDirectory(filePath)) {
            List<File> fs = FileUtil.loopFiles(filePath, f -> f.getName().endsWith(".java"));
            ExecutorService executorService = Executors.newFixedThreadPool(30);
            for (int i = 0; i < fs.size(); i++) {
                File src = fs.get(i);
                executorService.submit(()->{
                    checkFile(project,src,set,targetFile);
                });
            }
            executorService.shutdown();
        }
    }

    private void checkFile(Project project, File file, Set<String> set, File targetFile) {
        VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(file.getAbsolutePath());
        Application application = ApplicationManager.getApplication();
        application.runReadAction(()->{
            PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
            if(psiFile!=null) {
                PsiClass[] classes = PsiTreeUtil.getChildrenOfType(psiFile, PsiClass.class);
                if (classes != null) {
                    for (int i = 0; i < classes.length; i++) {
                        if (isClassImplementingAnyInterface(classes[i], set)) {
                            PsiField[] fields = classes[i].getAllFields();
                            if (fields.length > 0) {
                                for (PsiField field : fields) {
                                    String fieldName = field.getName();
                                    if (!"HUNDSUN_VERSION".equals(fieldName)) {
                                        FileLogUtil.log(targetFile, "存在成员变量:" + file.getAbsolutePath() + ":" + fieldName);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        });
       
    }



    // 判断类是否继承或实现了指定的接口集合中的任意一个接口
    public static boolean isClassImplementingAnyInterface(PsiClass psiClass, Collection<String> targetInterfaces) {
        // 获取类实现的所有接口
        PsiClassType[] implementedInterfaces = psiClass.getImplementsListTypes();

        // 遍历实现的接口，检查是否匹配
        for (PsiClassType implementedInterface : implementedInterfaces) {
            if (targetInterfaces.contains(implementedInterface.getCanonicalText())) {
                return true;
            }
        }

        // 获取类的父类，检查是否继承了目标接口
        PsiClassType[] extendedInterfaces = getSuperClassInterfaces(psiClass);
        for (PsiClassType superInterface : extendedInterfaces) {
            if (targetInterfaces.contains(superInterface.getCanonicalText())) {
                return true;
            }
        }

        return false;
    }

    // 获取父类接口（包括父类实现的接口）
    private static PsiClassType[] getSuperClassInterfaces(PsiClass psiClass) {
        PsiClass superClass = psiClass.getSuperClass();
        if (superClass != null) {
            return superClass.getImplementsListTypes();
        }
        return new PsiClassType[0];
    }

}
